package com.rc.web.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.rc.common.util.JsonUtil;
import com.rc.pojo.dto.identify.IdentifyAddDTO;
import com.rc.pojo.dto.identify.IdentifyQuery;
import com.rc.pojo.po.Identify;
import com.rc.pojo.po.IntegralDetail;
import com.rc.pojo.po.PlantItem;
import com.rc.web.mapper.IdentifyMapper;
import com.rc.web.service.FileService;
import com.rc.web.service.IdentifyService;
import com.rc.web.service.IntegralDetailService;
import com.rc.web.service.PlantItemService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import static com.mybatisflex.core.tenant.TenantManager.withoutTenantCondition;

/**
 * 识别服务实现类
 * 提供植物病虫害识别相关的业务逻辑实现
 */
@Service
@RequiredArgsConstructor
public class IdentifyServiceImpl extends ServiceImpl<IdentifyMapper, Identify> implements IdentifyService {
    // 文件服务
    private final FileService fileService;
    // 植物项服务
    private final PlantItemService plantItemService;
    // 积分明细服务
    private final IntegralDetailService integralDetailService;

    /**
     * 添加识别记录
     * @param dto 识别添加DTO
     */
    @Override
    public void add(IdentifyAddDTO dto) {
        // 检查植物ID是否为空
        var plantItemId = Objects.requireNonNull(dto.getPlantItemId(),"植物id不能为空");

        // 上传原始图片和病虫害图片
        var originalImg = fileService.upload(dto.getOriginalImg()).getUrl();
        var illImg = fileService.upload(dto.getIllImg()).getUrl();

        // 构建识别记录
        var identify = Identify.builder()
                .originalImg(originalImg)
                .identifyImg(illImg)
                .ripeNum(dto.getRipeNum())
                .totalNum(dto.getTotalNum())
                .build();

        var illName = dto.getIllName();

        // 如果识别到病虫害，则更新植物病虫害信息和积分
        if (StringUtils.isNotBlank(illName) && !illName.equals("null")) {
            // 将病虫害名称转换为对象列表
            var objList = JsonUtil.toObj(illName,
                    new TypeReference<List<Map<String, String>>>() {}
            );

            // 提取病虫害名称并去重
            var illNames = objList.stream()
                    .map(map -> map.get("name"))
                    .distinct()
                    .toList();

            // 设置病虫害名称并更新相关信息
            identify.setIllNames(illNames);
            updatePlantItemIlls(plantItemId, illNames);
            updateIntegral(plantItemId, illNames);
        }

        // 保存识别记录
        this.save(identify);
    }

    /**
     * 更新积分
     * @param plantItemId 植物项ID
     * @param illNames 病虫害名称列表
     */
    private void updateIntegral(Long plantItemId, List<String> illNames) {
        // 获取之前的识别记录
        var oldIdentify = mapper.selectByPlantItemId(plantItemId);

        // 获取之前的病虫害名称
        var oldIllNames = Optional.ofNullable(oldIdentify)
                .map(Identify::getIllNames)
                .orElse(List.of());

        // 为新发现的病虫害创建积分记录
        var list = illNames.stream()
                .filter(name -> !oldIllNames.contains(name))
                .map(name -> IntegralDetail.builder()
                        .title("找到一棵植株的病虫害：" + name)
                        .integral(20)
                        .build())
                .toList();

        // 批量保存积分记录
        integralDetailService.saveBatch(list);
    }

    /**
     * 更新植物项病虫害信息
     * @param plantItemId 植物项ID
     * @param illNames 病虫害名称列表
     */
    private void updatePlantItemIlls(Long plantItemId, List<String> illNames) {
        // 获取植物项信息
        var plantItem = withoutTenantCondition(() -> plantItemService.getById(plantItemId));
        var ills = plantItem.getIlls();

        // 如果存在病虫害信息，则更新
        if (ills != null) {
            ills.addAll(illNames);
            plantItem.setIlls(ills.stream().distinct().toList());
            plantItemService.updateById(plantItem);
        }
    }

    /**
     * 分页查询识别记录
     * @param query 查询条件
     * @return 分页结果
     */
    @Override
    public Page<Identify> getPage(IdentifyQuery query) {
        return mapper.selectPage(query);
    }
}
